package cc.rengu.igas.share.core.service.channel.upqc;

import cc.rengu.igas.channel.upqc.facade.base.Header;
import cc.rengu.igas.channel.upqc.facade.request.C2BPreAuthRevsalRequest;
import cc.rengu.igas.channel.upqc.facade.response.C2BPreAuthRevsalResponse;
import cc.rengu.igas.channel.upqc.facade.result.Result;
import cc.rengu.igas.share.common.constant.ShareParamConstant;
import cc.rengu.igas.share.common.constant.ShareServiceConstant;
import cc.rengu.igas.share.core.model.MchntInfo;
import cc.rengu.igas.share.core.realize.MchntService;
import cc.rengu.igas.share.core.realize.impl.MchntServiceImpl;
import cc.rengu.oltp.service.base.ChannelBaseService;
import cc.rengu.oltp.service.common.constant.AppParamConstant;
import cc.rengu.oltp.service.common.constant.TreeNodeConstant;
import cc.rengu.oltp.service.common.entity.*;
import cc.rengu.oltp.service.common.enums.*;
import cc.rengu.oltp.service.model.BizException;
import cc.rengu.oltp.service.model.BizResponse;
import cc.rengu.oltp.service.model.OrderInfo;
import cc.rengu.oltp.service.model.TxnInfo;
import cc.rengu.oltp.service.realize.DubboService;
import cc.rengu.oltp.service.realize.impl.DubboServiceImpl;
import cc.rengu.oltp.utility.util.*;

import java.util.Objects;
import java.util.Optional;

/**
 * C2B条码预授权冲正
 * Created by wangcheng on 2022/2/15 16:25
 */
public class C2BPreAuthRevsalService extends ChannelBaseService {
    @Override
    public Object callPreProc(TxnInfo txnInfo, ChannelCallCfg channelCallCfg, OrderInfo orderInfo) throws Exception {
        XmlTreeUtil xmlTreeUtil = new XmlTreeUtil();
        Header upqcHeader = new Header();
        upqcHeader.setInstId(xmlTreeUtil.getXmlTreeStringValue(TreeNodeConstant.INST_ID));
        upqcHeader.setChanlId(channelCallCfg.getMsgSrcId());
        upqcHeader.setSrcSysId(AppParamConstant.SYS_ID);
        upqcHeader.setBizType(AppParamConstant.DEFAULT_BIZ_TYPE);
        upqcHeader.setVersion(ShareParamConstant.DUBBO_VSERSION);
        upqcHeader.setTxnNum(channelCallCfg.getCallChannelTxn());
        upqcHeader.setTraceNo(xmlTreeUtil.getXmlTreeStringValue(TreeNodeConstant.SYS_SEQ_NUM) + channelCallCfg.getCallIndex());
        upqcHeader.setTransTime(xmlTreeUtil.getXmlTreeStringValue(TreeNodeConstant.TXN_DATE));
        upqcHeader.setTransDate(xmlTreeUtil.getXmlTreeStringValue(TreeNodeConstant.TXN_TIME));

        C2BPreAuthRevsalRequest c2BPreAuthRevsalRequest = new C2BPreAuthRevsalRequest();
        ConvertUtil.convertOutput(c2BPreAuthRevsalRequest);
        c2BPreAuthRevsalRequest.setHeader(upqcHeader);

        MchntService mchntService = new MchntServiceImpl();
        MchntInfo mchntInfo = mchntService.getMchntInfo(upqcHeader.getInstId(), xmlTreeUtil.getXmlTreeStringValue(TreeNodeConstant.MCHNT_NO));
        Optional<PayOrderInfo> payOrderInfoOpt = orderInfo.getPayOrderInfoList().stream().filter(item -> item.getMsgDstId().equals(ChannelEnum.UPQC.getChannelType())).findFirst();
        PayOrderInfo origPayOrderInfo = payOrderInfoOpt.orElse(null);
        c2BPreAuthRevsalRequest.setCupsMchntNo(mchntInfo.getCupsMchntNo());
        c2BPreAuthRevsalRequest.setCupsInstCode(mchntInfo.getCupsInstId());
        c2BPreAuthRevsalRequest.setPayQrCode(Objects.requireNonNull(origPayOrderInfo).getPayerAcctInfo());
        c2BPreAuthRevsalRequest.setOrderId(origPayOrderInfo.getSysSeqNum());
        c2BPreAuthRevsalRequest.setOrderTime(origPayOrderInfo.getTxnDate() + origPayOrderInfo.getTxnTime());
        return c2BPreAuthRevsalRequest;
    }

    @Override
    public PayOrderInfo generatePayOrderInfo(ChannelCallCfg channelCallCfg, OrderInfo orderInfo, Object request) throws Exception {
        return null;
    }

    @Override
    public Object callProc(ChannelCallCfg channelCallCfg, Object request) throws Exception {
        C2BPreAuthRevsalRequest c2BPreAuthRevsalRequest = (C2BPreAuthRevsalRequest) request;
        /* Step1：调用接口，获取结果 */
        Result<C2BPreAuthRevsalResponse> callResult;
        DubboService dubboService = new DubboServiceImpl();
        if (AppParamConstant.YES.equals(channelCallCfg.getSyncCallFlag())) {
            /* Step1.1：异步调用 */
            int iReturnCode;
            int callTimes = 0 == channelCallCfg.getSyncQueryRepeatNum() ? 1 : channelCallCfg.getSyncQueryRepeatNum();
            int gatTime = channelCallCfg.getSyncQueryRepeatTime();
            int gatType = StringUtil.isEmptyOrNull(channelCallCfg.getSyncQueryGapType()) ? 0 : Integer.parseInt(channelCallCfg.getSyncQueryGapType());
            if (ChannelCallModeEnum.LOCAL.getMode().equals(channelCallCfg.getChannelCallMode())) {
                /* Step1.1.1：异步应用内调用 */
                Class clasz = Class.forName(ShareServiceConstant.UPQC_SERVICE_INNER_PATH);
                iReturnCode = dubboService.asynCallDubboInnerMethod(clasz, ShareServiceConstant.UPQC_C2B_PRE_AUTH_REVSAL_METHOD, c2BPreAuthRevsalRequest, channelCallCfg.getSyncResultServiceName(), callTimes, gatType, gatTime);
            } else if (ChannelCallModeEnum.REMOTE.getMode().equals(channelCallCfg.getChannelCallMode())) {
                /* Step1.1.2：异步远程调用 */
                iReturnCode = dubboService.asynCallDubboService(ShareServiceConstant.UPQC_SERVICE, ShareServiceConstant.UPQC_C2B_PRE_AUTH_REVSAL_METHOD, c2BPreAuthRevsalRequest, channelCallCfg.getSyncResultServiceName(), callTimes, gatType, gatTime);
            } else {
                rglog.error("不支持的通道服务调用方式:{}，交易拒绝!", channelCallCfg.getChannelCallMode());
                throw new BizException(OltpRpcdEnum.CALL_BIZ_SERVICE_ERROR);
            }
            if (0 == iReturnCode) {
                return new BizResponse<>(OltpRpcdEnum.TRANS_SUCCESS.getRespCode(), OltpRpcdEnum.TRANS_SUCCESS.getRespDesc());
            } else {
                return new BizResponse<>(OltpRpcdEnum.CALL_BIZ_SERVICE_ERROR.getRespCode(), OltpRpcdEnum.CALL_BIZ_SERVICE_ERROR.getRespDesc());
            }
        } else {
            /* Step1.2：同步调用 */
            if (ChannelCallModeEnum.LOCAL.getMode().equals(channelCallCfg.getChannelCallMode())) {
                /* Step1.2.1：同步应用内调用 */
                Class clasz = Class.forName(ShareServiceConstant.UPQC_SERVICE_INNER_PATH);
                callResult = (Result<C2BPreAuthRevsalResponse>) dubboService.callDubboInnerMethod(clasz, ShareServiceConstant.UPQC_C2B_PRE_AUTH_REVSAL_METHOD, c2BPreAuthRevsalRequest);
            } else if (ChannelCallModeEnum.REMOTE.getMode().equals(channelCallCfg.getChannelCallMode())) {
                /* Step1.2.2：同步远程调用 */
                callResult = (Result<C2BPreAuthRevsalResponse>) dubboService.callDubboService(ShareServiceConstant.UPQC_SERVICE, ShareServiceConstant.UPQC_C2B_PRE_AUTH_REVSAL_METHOD, c2BPreAuthRevsalRequest);
            } else {
                rglog.error("不支持的通道服务调用方式:{}，交易拒绝!", channelCallCfg.getChannelCallMode());
                throw new BizException(OltpRpcdEnum.CALL_BIZ_SERVICE_ERROR);
            }
        }
        return callResult;
    }

    @Override
    public Object querySyncCallResult(PayOrderInfo payOrderInfo, Object request) {
        return null;
    }

    @Override
    public OrderInfo callResultOrderProc(OrderInfo orderInfo, String payOrderIndex, TransStatusEnum transStatusEnum, Object response) throws Exception {
        switch (transStatusEnum) {
            case TRANS_SUCC:
                /* 更新支付订单信息 */
                orderInfo.getUserOrderInfo().setOrderStatus(OrderStatusEnum.FINISH.getStatus());
                orderInfo.getUserOrderInfo().setTransStatus(TransStatusEnum.TRANS_SUCC.getStatus());
                orderInfo.getUserOrderInfo().setBizStatus(BizStatusEnum.REVSAL.getStatus());
                orderInfo.getUserOrderInfo().setUpdateTime(DateUtil.getCurrentDateTime("yyyy-MM-dd HH:mm:ss.SSS"));
                /* 更新商户订单信息 */
                orderInfo.getMchntOrderInfoList().forEach(item -> {
                    item.setTransStatus(TransStatusEnum.TRANS_SUCC.getStatus());
                    item.setBizStatus(BizStatusEnum.REVSAL.getStatus());
                    item.setUpdateTime(DateUtil.getCurrentDateTime("yyyy-MM-dd HH:mm:ss.SSS"));
                });
                /* 更新支付订单信息 */
                orderInfo.getPayOrderInfoList().forEach(item -> {
                    item.setTransStatus(TransStatusEnum.TRANS_SUCC.getStatus());
                    item.setBizStatus(BizStatusEnum.REVSAL.getStatus());
                    item.setUpdateTime(DateUtil.getCurrentDateTime("yyyy-MM-dd HH:mm:ss.SSS"));
                });
                break;
            case TRANS_TIMEOUT:
                rglog.warn("调用条码预授权权冲正调用超时!");
                break;
            case SYSTEM_REJECT:
                rglog.warn("调用条码预授权权冲正调用失败!");
                break;
            default:
                break;
        }
        return orderInfo;
    }
}
